#include "InteractionElement.h"

namespace OpenNano
{
    REGISTER_OBJECT_FACTORY ( InteractionElement, INTERACTION_TAG );

    InteractionElement::InteractionElement(TiXmlElement * element) :
                        ConfigElement(element), logger(log4cplus::Logger::getInstance( INTERACTION_TAG )),
                        _everything_is_good_so_far(true), _keyboards(), _inputs(), _outputs(),
                        _mouse(0), _haptic(0)

                {
                }

    InteractionElement::~InteractionElement()
    {
        _keyboards.clear();
        _inputs.clear();
        _outputs.clear();
    }

    void InteractionElement::init()
    {
        LOG4CPLUS_INFO(logger, "Interaction element: initialized");
    }

    const KeyboardsMap& InteractionElement::getKeyboards() const
    {
        return _keyboards;
    }

    KeyboardElement * InteractionElement::getKeyboard(const std::string& name)
    {
        KeyboardElement * k = 0;
        KeyboardsMap::iterator it = _keyboards.find(name);
        if (it!=_keyboards.end())
        {
            k=it->second;
        }
        else
        {
            LOG4CPLUS_WARN(logger, "Keyboard not found:");
            LOG4CPLUS_WARN(logger, name);
        }
        return k;
    }


    const InputsMap& InteractionElement::getInputs() const
    {
        return _inputs;
    }

    InputElement * InteractionElement::getInput(const std::string& name)
    {
        InputElement * inp = 0;
        InputsMap::iterator it = _inputs.find(name);
        if (it!=_inputs.end())
        {
            inp=it->second;
        }
        else
        {
            LOG4CPLUS_WARN(logger, "Input not found:");
            LOG4CPLUS_WARN(logger, name);
        }
        return inp;
    }


    const OutputsMap& InteractionElement::getOutputs() const
    {
        return _outputs;
    }

    OutputElement * InteractionElement::getOutput(const std::string& name)
    {
        OutputElement * out = 0;
        OutputsMap::iterator it = _outputs.find(name);
        if (it!=_outputs.end())
        {
            out=it->second;
        }
        else
        {
            LOG4CPLUS_WARN(logger, "Output not found:");
            LOG4CPLUS_WARN(logger, name);
        }
        return out;
    }

    MouseElement * InteractionElement::getMouse()
    {
        return _mouse;
    }

    HapticElement * InteractionElement::getHapticDevice()
    {
        return _haptic;
    }

    void InteractionElement::attributeFound(TiXmlAttribute * attribute )
    {
        //attribute not recognized
        LOG4CPLUS_WARN(logger, "Attribute not recognized:");
        LOG4CPLUS_WARN(logger, attribute->NameTStr());

        unknownAttributeFound(attribute);
        _everything_is_good_so_far=false;
    }

    void InteractionElement::childElementFound(TiXmlElement * childElement)
    {
        if ( !_mouse && childElement->ValueStr().compare(MOUSE_TAG) == 0 )
        {
            _mouse = (MouseElement *)ConfigElementFactory::getInstance().create(MOUSE_TAG)(childElement);
            _everything_is_good_so_far = _mouse->process();
        }
        else if ( !_haptic && childElement->ValueStr().compare(HAPTIC_TAG) == 0 )
        {
            _haptic = (HapticElement *)ConfigElementFactory::getInstance().create(HAPTIC_TAG)(childElement);
            _everything_is_good_so_far = _haptic->process();
        }
        else if ( childElement->ValueStr().compare(KEYBOARD_TAG) == 0 )
        {
            KeyboardElement * k = (KeyboardElement *)ConfigElementFactory::getInstance().create(KEYBOARD_TAG)(childElement);
            if (k)
            {
                _everything_is_good_so_far = k->process();
                if (_everything_is_good_so_far)
                {
                    _keyboards[k->getInterpreter()] = k;
                }
                else
                {
                    delete k;
                    _everything_is_good_so_far=false;
                    LOG4CPLUS_ERROR(logger, "Keyboard element not processed correctly");
                }
            }
            else
            {
                LOG4CPLUS_WARN(logger, "Keyboard element not registered in the factory:");
                LOG4CPLUS_WARN(logger, childElement->ValueStr());

                unknownElementFound(childElement);
                _everything_is_good_so_far=false;
                _everything_is_good_so_far=false;
            }
        }
        else if ( childElement->ValueStr().compare(INPUT_TAG) == 0 )
        {
            InputElement * inp = (InputElement *)ConfigElementFactory::getInstance().create(INPUT_TAG)(childElement);
            if (inp)
            {
                _everything_is_good_so_far = inp->process();
                if (_everything_is_good_so_far)
                {
                    _inputs[inp->getName()] = inp;
                }
                else
                {
                    delete inp;
                    _everything_is_good_so_far=false;
                    LOG4CPLUS_ERROR(logger, "Input element not processed correctly");
                }
            }

            else
            {
                LOG4CPLUS_WARN(logger, "Input element not registered in the factory:");
                LOG4CPLUS_WARN(logger, childElement->ValueStr());

                unknownElementFound(childElement);
                _everything_is_good_so_far=false;
            }
        }
        else if ( childElement->ValueStr().compare(OUTPUT_TAG) == 0 )
        {
            OutputElement * out = (OutputElement *)ConfigElementFactory::getInstance().create(OUTPUT_TAG)(childElement);
            if (out)
            {
                _everything_is_good_so_far = out->process();
                if (_everything_is_good_so_far)
                {
                    _outputs[out->getName()] = out;
                }
                else
                {
                    delete out;
                    _everything_is_good_so_far=false;
                    LOG4CPLUS_ERROR(logger, "Output element not processed correctly");
                }
            }

            else
            {
                LOG4CPLUS_WARN(logger, "Output element not registered in the factory:");
                LOG4CPLUS_WARN(logger, childElement->ValueStr());

                unknownElementFound(childElement);
                _everything_is_good_so_far=false;
            }
        }
        else
        {
            //Element not recognized
            LOG4CPLUS_WARN(logger, "Child element not recognized:");
            LOG4CPLUS_WARN(logger, childElement->ValueStr());

            unknownElementFound(childElement);
            _everything_is_good_so_far=false;
        }

        return;
    }

    void InteractionElement::textFound(const char * text)
    {
        LOG4CPLUS_WARN(logger, "Text not recognized:");
        LOG4CPLUS_WARN(logger, text);

        unknownTextFound(text);
    }

    bool InteractionElement::postConfiguration()
    {
        return _everything_is_good_so_far;
    }


}
